#pragma once

#include <algorithm/analytical_model/algorithm/cuda/receiver/Receiver.cuh>

#include <tuple>

/**
 * PS:
 *  size_:
 *      size_.x is the radius of cylinder
 *      size_.y is the height of cylinder
 *      size_.z has no meaning
 */

namespace solar::cuda
{
    class CylinderReceiver : public Receiver
    {
        public:
            __device__ CylinderReceiver() = default;
            __host__ CylinderReceiver(cudaStream_t stream = nullptr);
            void init(float pixel_per_meter_for_receiver) override;
            void setResolution(float pixel_per_meter_for_receiver) override;
            __host__ __device__ auto getFocusCenter(const float3& heliostat_position) -> float3 override;
            /**
             * 1) Define equation:
             *      -ray equation: p(t) = (orig - pos) + t * dir     (1)
             *      -cylinder equation: z^2 + m^2 * x^2 = r^2     (r = size.x,  m = 1)    (2)
             * 2) combine equation (1) and (2):
             *      calculate delta: delta = b^2 - 4ac
             *          -if delta >= 0, may have intersection
             *          -if delta < 0, no intersection
             * 3) calculate t and point of intersection
             *          -if t < 0, wrong direction, so remain the positive solution
             *          -if intersect_point.z is not belonging to the range [0, size.z], not
             * effective intersection and return false.
             */
            /// @returns {t, u, v, isIntersected}
            __device__ __host__ auto intersect(const float3& orig, const float3& dir)
                -> std::tuple<float, float, float, bool>;

        private:
            __device__ __host__ auto isInsideCylinder(const float3& orig) -> bool;
    };
} // namespace solar::cuda
